package com.ruyuan.gateway.server.realm;

import com.ruyuan.gateway.sdk.model.GatewaySDKProperties;
import com.ruyuan.gateway.sdk.model.UserAccountInfo;
import com.ruyuan.gateway.sdk.model.UserAuthorities;
import com.ruyuan.gateway.server.model.ApiPermission;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

import java.time.Duration;

import static com.ruyuan.gateway.sdk.model.GatewayConstants.USER_AUTH_PREFIX;

/**
 * @author xx
 */
@Component
public class UserPermissionRealm extends AuthorizingRealm {

    @Resource(name = "gatewayRedisTemplate")
    private RedisTemplate redisTemplate;

    @Autowired
    private GatewaySDKProperties properties;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        UserAccountInfo user = (UserAccountInfo) SecurityUtils.getSubject().getPrincipal();
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        BoundValueOperations operations = redisTemplate.boundValueOps(USER_AUTH_PREFIX + user.getUserId());
        UserAuthorities userAuthorities = (UserAuthorities) operations.get();
        if (userAuthorities != null) {
            simpleAuthorizationInfo.addObjectPermission(new ApiPermission(userAuthorities.getAuthorityCodes()));
            //刷新下缓存
            operations.expire(Duration.ofMillis(properties.getSessionTimeout() + 300000L));
        }
        return simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        return null;
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        // 不做登录验证
        return false;
    }
}
